﻿using System;
using System.Windows.Forms;

namespace InputHandlers.KeyboardHandling
{
    /// <summary>
    /// Toggle key.
    /// </summary>
    public class ToggleKey
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ToggleKey"/> class with the key definition.
        /// </summary>
        /// <param name="keyDefinition">Key definition.</param>
        /// <param name="operationToTake">An operation to take when requesting to verify the validity of an input against this key-definition.</param>
        /// <param name="isOn">Whether the key is started as toggled on.</param>
        public ToggleKey(Keys keyDefinition, Action operationToTake, bool isOn = false)
        {
            KeyDefinition = keyDefinition;
            OperationToTake = operationToTake;
            On = isOn;
        }

        /// <summary>
        /// Gets the definition of the key toggling tracker.
        /// </summary>
        /// <value>The key definition.</value>
        public Keys KeyDefinition { get; private set; }

        /// <summary>
        /// Gets a value indicating whether this <see cref="ToggleKey"/> is toggled on.
        /// </summary>
        /// <value><c>true</c> if on; otherwise, <c>false</c>.</value>
        public bool On { get; private set; }

        protected Action OperationToTake { get; private set; }

        /// <summary>
        /// Toggles the state of the toggle-key.
        /// </summary>
        /// <param name="newState">If given - the absolute state. Otherwise, simply toggle the state.</param>
        public void ToggleState(bool? newState = null)
        {
            if (newState.HasValue)
            {
                On = newState.Value;
            }
            else
            {
                On = !On;
            }
        }

        /// <summary>
        /// Toggles the state of the toggle-key, provided that the given input key contains the key defined for this toggle-key.
        /// If the given key belongs to this toggle key, execute the defined action.
        /// </summary>
        /// <param name="inputKey">The input key to check with the definition of this key.</param>
        /// <param name="newState">New state.</param>
        /// <returns>Whether the toggle key was toggled.</returns>
        public bool ToggleState(Keys inputKey, bool? newState = null)
        {
            var isContained = CheckContained(inputKey);

            if (isContained)
            {
                ToggleState(newState);
            }

            if (On)
            {
                OperationToTake();
            }

            return isContained;
        }

        /// <summary>
        /// Verifies that the toggle-key is contained in the given key.
        /// </summary>
        /// <returns>Whether this toggle-key is contained in the given input.</returns>
        /// <param name="inputKey">The key to check if this toggle-key is contained.</param>
        public virtual bool CheckContained(Keys inputKey)
        {
            return inputKey == KeyDefinition;
        }
    }
}

